package com.ikingtech.platform.service.oidc.client.controller;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ikingtech.framework.sdk.context.exception.FrameworkException;
import com.ikingtech.framework.sdk.data.mybatisplus.helper.base.BaseController;
import com.ikingtech.framework.sdk.utils.Tools;
import com.ikingtech.framework.sdk.web.annotation.ApiController;
import com.ikingtech.platform.service.oidc.client.entity.OidcClientDO;
import com.ikingtech.platform.service.oidc.client.entity.OidcClientRedirectUriDO;
import com.ikingtech.platform.service.oidc.client.model.OidcClientDTO;
import com.ikingtech.platform.service.oidc.client.model.OidcClientQueryParamDTO;
import com.ikingtech.platform.service.oidc.client.model.OidcClientRedirectUriDTO;
import com.ikingtech.platform.service.oidc.client.service.OidcClientRedirectUriRepository;
import com.ikingtech.platform.service.oidc.client.service.OidcClientRepository;

import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @author tie yan
 */
@ApiController(value = "/oidc-client", name = "OIDC客户端管理", description = "OIDC客户端管理")
public class OidcClientController extends BaseController<OidcClientDTO, OidcClientDO, OidcClientQueryParamDTO> {

    private final OidcClientRedirectUriRepository redirectUriRepo;

    protected OidcClientController(OidcClientRepository repo,
                                   OidcClientRedirectUriRepository redirectUriRepo) {
        super(repo, OidcClientDTO.class, OidcClientDO.class);
        this.redirectUriRepo = redirectUriRepo;
    }

    @Override
    protected void beforeSave(OidcClientDTO client) {
        if (this.repo.exists(Wrappers.<OidcClientDO>lambdaQuery().eq(OidcClientDO::getName, client.getName()))) {
            throw new FrameworkException("duplicateClientName");
        }
    }

    @Override
    protected void afterSave(OidcClientDTO client, OidcClientDO entity) {
        if (Tools.Coll.isNotBlank(client.getRedirectUris())) {
            this.redirectUriRepo.saveBatch(Tools.Coll.convertList(client.getRedirectUris(), redirectUri -> {
                OidcClientRedirectUriDO redirectUriEntity = Tools.Bean.copy(redirectUri, OidcClientRedirectUriDO.class);
                redirectUriEntity.setId(Tools.Id.uuid());
                redirectUriEntity.setClientId(entity.getId());
                return redirectUriEntity;
            }));
        }
    }

    @Override
    protected void afterDelete(String clientId) {
        this.redirectUriRepo.remove(Wrappers.<OidcClientRedirectUriDO>lambdaQuery().eq(OidcClientRedirectUriDO::getClientId, clientId));
    }

    @Override
    protected List<String> beforeQuery(OidcClientQueryParamDTO queryParam) {
        return Tools.Str.isNotBlank(queryParam.getRedirectUri()) ?
                this.redirectUriRepo.listObjs(Wrappers.<OidcClientRedirectUriDO>lambdaQuery()
                        .select(OidcClientRedirectUriDO::getClientId)
                        .like(OidcClientRedirectUriDO::getRedirectUri, queryParam.getRedirectUri())) :
                Collections.emptyList();
    }

    @Override
    protected List<OidcClientDTO> modelConvert(List<OidcClientDO> entities) {
        List<OidcClientDTO> oidcClients = super.modelConvert(entities);
        if (Tools.Coll.isNotBlank(entities)) {
            List<OidcClientRedirectUriDO> redirectUriEntities = this.redirectUriRepo.list(Wrappers.<OidcClientRedirectUriDO>lambdaQuery()
                    .in(OidcClientRedirectUriDO::getClientId, Tools.Coll.convertList(entities, OidcClientDO::getId)));
            Map<String, List<OidcClientRedirectUriDO>> redirectUriMap = Tools.Coll.convertGroup(redirectUriEntities, OidcClientRedirectUriDO::getClientId);
            oidcClients.forEach(client -> client.setRedirectUris(Tools.Coll.convertList(redirectUriMap.getOrDefault(client.getId(), Collections.emptyList()), redirectUriEntity -> Tools.Bean.copy(redirectUriEntity, OidcClientRedirectUriDTO.class))));
        }
        return oidcClients;
    }

    @Override
    protected OidcClientDTO modelConvert(OidcClientDO entity) {
        OidcClientDTO oidcClient = super.modelConvert(entity);
        List<OidcClientRedirectUriDO> redirectUriEntities = this.redirectUriRepo.list(Wrappers.<OidcClientRedirectUriDO>lambdaQuery()
                .eq(OidcClientRedirectUriDO::getClientId, entity.getId()));
        oidcClient.setRedirectUris(Tools.Coll.convertList(redirectUriEntities, redirectUriEntity -> Tools.Bean.copy(redirectUriEntity, OidcClientRedirectUriDTO.class)));
        return oidcClient;
    }
}
